package com.sskj.ws.factory;

import jakarta.websocket.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
public class DeviceSubscriptionFactory {

    // 设备CODE ---> 订阅它的所有会话集合
    private final Map<String, Set<Session>> deviceSubscriptionMap = new ConcurrentHashMap<>();

    /**
     * 订阅
     * @param deviceCode 设备CODE
     * @param session 会话实例
     */
    public void subscribe(Session session, String deviceCode) {
        deviceSubscriptionMap.computeIfAbsent(deviceCode, k -> new CopyOnWriteArraySet<>()).add(session);
    }

    /**
     * 批量订阅
     * @param session 会话ID
     * @param deviceCodes 设备集合
     */
    public void batchSubscribe(Session session, Collection<String> deviceCodes) {
       if (deviceCodes != null && !deviceCodes.isEmpty()) {
           for (String deviceCode : deviceCodes) {
               subscribe(session, deviceCode);
           }
       }
    }

    /**
     * 断开连接清理无效Session
     * @param session 会话
     */
    public void clearSession(Session session) {
        for (Set<Session> sessions : deviceSubscriptionMap.values()) {
            sessions.remove(session);
        }

        deviceSubscriptionMap.entrySet().removeIf(entry -> entry.getValue().isEmpty());
    }

    /**
     * 获取订阅设备的所有会话
     * @param deviceCode 设备CODE
     * @return 集合
     */
    public Set<Session> getSubscribers(String deviceCode) {
        return deviceSubscriptionMap.getOrDefault(deviceCode, Set.of());
    }

    /**
     * 向指定设备的订阅用户广播信息
     * @param deviceCode 设备CODE
     * @param message 消息
     */
    public void broadcastToDevice(String deviceCode, String message) {
        Set<Session> sessions = getSubscribers(deviceCode);

        for (Session session : sessions) {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                } catch (Exception e) {
                    log.info("推送消息失败到会话：{}，错误：{}", session.getId(), e.getMessage());
                }
            }
        }
    }
}
